package org.epes.laboratory.vcn.service;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;
import org.activiti.engine.impl.el.Expression;
import org.epes.laboratory.vcn.application.OptimizationApplication;
import org.epes.laboratory.vcn.utils.POICMISHelper;
//import org.epes.laboratory.vcn.utils.SpringApplicationContext;
//import org.activiti.explorer.NotificationManager;

public class RunOptimizationTask implements JavaDelegate {
	
	private Expression inputTemplateId;
	private Expression solutionsFolderId;
	private Expression scriptPath;
	private Expression inputPath;
	private Expression outputPath;

	private static final String EXCEL_MIMETYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";	
	
	public void execute(DelegateExecution execution) throws Exception {
		
		// Get optimizationApplication process variable and update all values - INIT		
		
		OptimizationApplication oa = (OptimizationApplication) execution.getVariable("optimizationApplication");
		
		// x0y0
		String x0y0 = (String) execution.getVariable("x0y0");
		String x0 = x0y0.split(",")[0];
		String y0 = x0y0.split(",")[1];
		
		oa.setX0(Float.parseFloat(x0));
		oa.setY0(Float.parseFloat(y0));
		
		// x1y1
		String x1y1 = (String) execution.getVariable("x1y1");
		String x1 = x1y1.split(",")[0];
		String y1 = x1y1.split(",")[1];
		
		oa.setX1(Float.parseFloat(x1));
		oa.setY1(Float.parseFloat(y1));
		
		// x2y2
		String x2y2 = (String) execution.getVariable("x2y2");
		String x2 = x2y2.split(",")[0];
		String y2 = x2y2.split(",")[1];
		
		oa.setX2(Float.parseFloat(x2));
		oa.setY2(Float.parseFloat(y2));
		
		// x3y3
		String x3y3 = (String) execution.getVariable("x3y3");
		String x3 = x3y3.split(",")[0];
		String y3 = x3y3.split(",")[1];
		
		oa.setX3(Float.parseFloat(x3));
		oa.setY3(Float.parseFloat(y3));
		
		// x4y4
		String x4y4 = (String) execution.getVariable("x4y4");
		String x4 = x4y4.split(",")[0];
		String y4 = x4y4.split(",")[1];
		
		oa.setX4(Float.parseFloat(x4));
		oa.setY4(Float.parseFloat(y4));		
		
		// Get optimizationApplication process variable and update all values - END
		
		// Get the excel template and fill in with OptimizationApplication variables - INIT		
		
		// Get the excel template EPES_Lab_sim_INPUT-OUTPUT_02.xlsx from the VCN using CMIS		
		POICMISHelper helper = new POICMISHelper();		
		helper.openWorkbook(inputTemplateId.getValue(execution).toString());
		
		// Fill in the values in the template
		// Set x0, y0 values		
		helper.setCellValue(oa.getX0(), 10, 2, false);
		helper.setCellValue(oa.getY0(), 10, 3, false);
		
		// Set x1, y1 values
		helper.setCellValue(oa.getX1(), 11, 2, false);
		helper.setCellValue(oa.getY1(), 11, 3, false);
		
		// Set x2, y2 values
		helper.setCellValue(oa.getX2(), 12, 2, false);
		helper.setCellValue(oa.getY2(), 12, 3, false);
		
		// Set x3, y3 values
		helper.setCellValue(oa.getX3(), 13, 2, false);
		helper.setCellValue(oa.getY3(), 13, 3, false);
		
		// Set x4, y4 values
		helper.setCellValue(oa.getX4(), 14, 2, false);
		helper.setCellValue(oa.getY4(), 14, 3, false);
				
		// Set co2ManagedKnowledge value
		helper.setCellValue(oa.getCo2ManagedKnowledge(), 10, 6, false);
		
		// Evaluate all the cells with formulas
		helper.evaluateAll();		
		
		// Get the excel template and fill in with OptimizationApplication variables - END		
		
		// Send the excelSimulator to SOMO through REST or other Web Services technology - INIT
		
		// Write the document into the file	system		
		helper.saveDocumentToFileSystem(inputPath.getValue(execution).toString());
		
		// Run SOMORESTLayer script
		long lStartTime = new Date().getTime(); // process start time
		List<String> command = new ArrayList<String>();
	    command.add(scriptPath.getValue(execution).toString());
	    command.add("name");
	    command.add("password");
	    ProcessBuilder builder = new ProcessBuilder(command);
	    System.out.println("SOMO Optimization started!");
	    final Process process = builder.start();
	    InputStream is = process.getErrorStream();
	    InputStreamReader isr = new InputStreamReader(is);
	    BufferedReader br = new BufferedReader(isr);
	    String line;
	    while ((line = br.readLine()) != null) {
	      System.out.println(line);
	    }
	    long lEndTime = new Date().getTime(); // process end time
	    long difference = lEndTime - lStartTime; // difference
	    // Send a notification to Activiti Explorer after the transaction ends
	    //NotificationManager notificationManager = (NotificationManager) SpringApplicationContext.getBean("notificationManager");
	    //notificationManager.showWarningNotification("optimization.end.caption", "optimization.end.description", String.valueOf(difference));
	    System.out.println("SOMO Optimization finished. Elapsed time: " + difference + " ms.");
		
		// Send the excelSimulator to SOMO through REST or other Web Services technology - END
		
		// Get the solution from SOMO - INIT
		
		File file = new File(outputPath.getValue(execution).toString());
		FileInputStream fis = null;
		ByteArrayOutputStream excelSolution = new ByteArrayOutputStream();
		try {
			fis = new FileInputStream(file); 
			System.out.println("EPES: The file '" + file.getPath() + "' has been read. " +
					"File size to read (in bytes) : "
					+ fis.available()); 
			int content;
			while ((content = fis.read()) != -1) {	
				excelSolution.write(content);
			}
 
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (fis != null)
					fis.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		
		// Get the solution from SOMO - END
				
		// Save the solution to the VCN. Set the solution as an OptimizationApplication field and update 
		// optimizationApplication process variable - INIT		
		
		// Save the solution to the VCN
		helper.saveDocumentToFolder(excelSolution, solutionsFolderId.getValue(execution).toString(), 
				"ExcelSolution", ".xslx", EXCEL_MIMETYPE);
		
		// Set the excelSolution as an OptimizationApplication field 		
		oa.setExcelSolution(excelSolution.toByteArray());
		// Set the excelSolution file name as an OptimizationApplication field
		oa.setExcelSolutionName(helper.getDocumentName());
		
		// Update optimizationApplication process variable
		execution.setVariable("optimizationApplication", oa);	
		
		// Save the solution to the VCN. Set the solution as an OptimizationApplication field and update 
		// optimizationApplication process variable - END
		
	}
}
